package com.swinginwind.flexutils.components
{
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	
	import mx.controls.Button;
	import mx.core.IFlexDisplayObject;
	import mx.core.mx_internal;
	import mx.events.FlexEvent;
	import mx.core.IUITextField;
	
	use namespace mx_internal;
	
	//--------------------------------------
	//  Styles
	//-------------------------------------- 
	
	/**
	 *  Name of CSS style declaration that specifies styles for the text of the
	 *  selected button.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	[Style(name="selectedButtonTextStyleName", type="String", inherit="no")]
	
	//--------------------------------------
	//  Excluded APIs
	//--------------------------------------
	
	[Exclude(name="horizontalLineScrollSize", kind="property")]
	[Exclude(name="horizontalPageScrollSize", kind="property")]
	[Exclude(name="horizontalScrollBar", kind="property")]
	[Exclude(name="horizontalScrollPolicy", kind="property")]
	[Exclude(name="horizontalScrollPosition", kind="property")]
	[Exclude(name="maxHorizontalScrollPosition", kind="property")]
	[Exclude(name="maxVerticalScrollPosition", kind="property")]
	[Exclude(name="verticalLineScrollSize", kind="property")]
	[Exclude(name="verticalPageScrollSize", kind="property")]
	[Exclude(name="verticalScrollBar", kind="property")]
	[Exclude(name="verticalScrollPolicy", kind="property")]
	[Exclude(name="verticalScrollPosition", kind="property")]
	
	[Exclude(name="scroll", kind="event")]
	[Exclude(name="click", kind="event")]
	
	[Exclude(name="backgroundAlpha", kind="style")]
	[Exclude(name="backgroundAttachment", kind="style")]
	[Exclude(name="backgroundColor", kind="style")]
	[Exclude(name="backgroundImage", kind="style")]
	[Exclude(name="backgroundSize", kind="style")]
	[Exclude(name="borderColor", kind="style")]
	[Exclude(name="borderSides", kind="style")]
	[Exclude(name="borderSkin", kind="style")]
	[Exclude(name="borderStyle", kind="style")]
	[Exclude(name="borderThickness", kind="style")]
	[Exclude(name="cornerRadius", kind="style")]
	[Exclude(name="dropShadowColor", kind="style")]
	[Exclude(name="dropShadowEnabled", kind="style")]
	[Exclude(name="horizontalScrollBarStyleName", kind="style")]
	[Exclude(name="shadowCapColor", kind="style")]
	[Exclude(name="shadowColor", kind="style")]
	[Exclude(name="shadowDirection", kind="style")]
	[Exclude(name="shadowDistance", kind="style")]
	[Exclude(name="verticalScrollBarStyleName", kind="style")]
	
	//--------------------------------------
	//  Other metadata
	//-------------------------------------- 
	
	
	[Alternative(replacement="spark.components.ButtonBar", since="4.0")]
	
	[DefaultTriggerEvent("itemClick")]

	/**
	 * @author jimmy
	 * @E-mail: swinginwind@gmail.com
	 * @version 1.0.0
	 * 创建时间：2013-1-4 下午1:52:24
	 * 
	 */
	public class CustomToggleButtonBar extends CustomButtonBar
	{
		public function CustomToggleButtonBar()
		{
			super();
		}
		
		/**
		 *  @private.
		 */
		private var initializeSelectedButton:Boolean = true;
		
		/**
		 *  @private
		 *  Name of style used to specify selectedButtonTextStyleName.
		 *  Overridden by TabBar.
		 */
		mx_internal var selectedButtonTextStyleNameProp:String =
			"selectedButtonTextStyleName";
		
		//--------------------------------------------------------------------------
		//
		//  Overridden properties
		//
		//--------------------------------------------------------------------------
		
		//----------------------------------
		//  selectedIndex
		//----------------------------------
		
		/**
		 *  @private
		 *  Storage for the selectedIndex property.
		 */
		private var _selectedIndex:int = -2;
		
		/**
		 *  @private.
		 */
		private var selectedIndexChanged:Boolean = false;
		
		[Bindable("click")]
		[Bindable("valueCommit")]
		[Inspectable(category="General")]
		
		/**
		 *  Index of the selected button.
		 *  Indexes are in the range of 0, 1, 2, ..., n - 1,
		 *  where <i>n</i> is the number of buttons.
		 *
		 *  <p>The default value is 0.
		 *  A value of -1 deselects all the buttons in the bar.</p>
		 *  
		 *  @langversion 3.0
		 *  @playerversion Flash 9
		 *  @playerversion AIR 1.1
		 *  @productversion Flex 3
		 */
		override public function get selectedIndex():int
		{
			return super.selectedIndex;
			//return _selectedIndex;
		}
		
		/**
		 *  @private.
		 */
		override public function set selectedIndex(value:int):void
		{  
			//#SDK-15690 - if the user has asked for -1 (no child selected) then we must preserve this
			if (value == selectedIndex && value != -1)
				return;
			
			// If the buttons have not been created yet, store the selectedIndex.
			if (numChildren == 0)
			{
				_selectedIndex = value;
				selectedIndexChanged = true;
			}
			
			// Otherwise set the index locally and invalidate properties.
			if ( value < numChildren)
			{
				_selectedIndex = value;
				selectedIndexChanged = true;
				
				invalidateProperties();
				dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
			} 
		}
		
		//--------------------------------------------------------------------------
		//
		//  Properties
		//
		//--------------------------------------------------------------------------
		
		//----------------------------------
		//  toggleOnClick
		//----------------------------------
		
		/**
		 *  @private
		 *  Storage for the toggleOnClick property.
		 */
		private var _toggleOnClick:Boolean = false;
		
		[Inspectable(category="General", defaultValue="false")]
		
		/**
		 *  Specifies whether the currently selected button can be deselected by
		 *  the user.
		 *
		 *  By default, the currently selected button gets deselected
		 *  automatically only when another button in the group is selected.
		 *  Setting this property to <code>true</code> lets the user
		 *  deselect it.
		 *  When the currently selected button is deselected,
		 *  the <code>selectedIndex</code> property is set to <code>-1</code>.
		 *
		 *  @default false
		 *  
		 *  @langversion 3.0
		 *  @playerversion Flash 9
		 *  @playerversion AIR 1.1
		 *  @productversion Flex 3
		 */
		public function get toggleOnClick():Boolean
		{
			return _toggleOnClick;
		}
		
		/**
		 *  @private
		 */
		public function set toggleOnClick(value:Boolean):void
		{
			_toggleOnClick = value;
		}
		
		//--------------------------------------------------------------------------
		//
		//  Overridden methods: UIComponent
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  @private
		 */
		override protected function commitProperties():void
		{
			super.commitProperties();
			
			if (selectedIndexChanged)
			{
				hiliteSelectedNavItem(_selectedIndex);
				
				// Update parent index.
				super.selectedIndex = _selectedIndex;
				
				selectedIndexChanged = false;
			}
		}
		
		/**
		 *  @private
		 */
		override protected function updateDisplayList(unscaledWidth:Number,
													  unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			// Select the first selectedIndex in the UI. If the user has defined it,
			// the value will be waiting in the selectedIndex property
			if (initializeSelectedButton)
			{
				initializeSelectedButton = false;
				
				var index:int = _selectedIndex;
				if (index == -2 )
				{
					if (numChildren > 0)
						index = 0;
					else
						index = -1;
				}
				hiliteSelectedNavItem(index);
			}
		}
		
		/**
		 *  @private
		 */
		override public function styleChanged(styleProp:String):void
		{
			var allStyles:Boolean = styleProp == null || styleProp == "styleName";
			
			super.styleChanged(styleProp);
			
			if (allStyles ||
				styleProp == selectedButtonTextStyleNameProp)
			{
				if (selectedIndex != -1 && selectedIndex < numChildren)
				{
					var child:Button = Button(getChildAt(selectedIndex));
					if (child)
					{
						var selectedButtonTextStyleName:String =
							getStyle(selectedButtonTextStyleNameProp);
						
						child.getTextField().styleName =
							selectedButtonTextStyleName ?
							selectedButtonTextStyleName :
							"activeButtonStyle";
					}
				}
			}
		}
		
		//--------------------------------------------------------------------------
		//
		//  Overridden methods: NavBar
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  @private
		 */
		override protected function createNavItem(
			label:String,
			icon:Class = null):IFlexDisplayObject
		{
			var b:Button = Button(super.createNavItem(label, icon));
			b.toggle = true;
			return b;
		}
		
		/**
		 *  @private
		 */
		override protected function hiliteSelectedNavItem(index:int):void
		{
			var child:Button;
			
			// Un-hilite the current selection
			if (selectedIndex != -1 && selectedIndex < numChildren)
			{
				child = Button(getChildAt(selectedIndex));
				
				child.selected = false;
				child.getTextField().styleName = child;
				
				child.invalidateDisplayList();
				child.invalidateSize();
			}
			
			// Set new index
			super.selectedIndex = index;
			_selectedIndex = index;
			
			if (index > -1)
			{
				// Hilite the new selection
				child = Button(getChildAt(selectedIndex));
				
				child.selected = true;
				
				//var selectedButtonTextStyleName:String =
				//	getStyle(selectedButtonTextStyleNameProp);
				var selectedButtonTextStyleName:String = "activeButtonStyle";
				
				var textField:IUITextField = child.getTextField();
				textField.styleName =
					selectedButtonTextStyleName ?
					selectedButtonTextStyleName :
					"activeButtonStyle";
				
				child.invalidateDisplayList();
			} 
			
			
		}
		
		/**
		 *  @private
		 */
		override protected function resetNavItems():void
		{
			var selectedButtonTextStyleName:String =
				getStyle(selectedButtonTextStyleNameProp);
			
			// Need to reset the index values, selection state,
			// and selected text style...
			var n:int = numChildren;
			for (var i:int = 0; i < n; i++)
			{
				var child:Button = Button(getChildAt(i));
				
				if (i == selectedIndex)
				{
					child.selected = true;
					child.getTextField().styleName =
						selectedButtonTextStyleName ?
						selectedButtonTextStyleName :
						"activeButtonStyle";
				}
				else
				{
					child.selected = false;
					child.getTextField().styleName = child;
				}
			}
			
			super.resetNavItems();
		}
		
		//--------------------------------------------------------------------------
		//
		//  Methods
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  @private
		 *  Select the button at the specified index.
		 */
		mx_internal function selectButton(index:int,
										  updateFocusIndex:Boolean = false,
										  trigger:Event = null):void
		{
			// 143958
			_selectedIndex = index;
			
			if (updateFocusIndex)
			{
				drawButtonFocus(focusedIndex, false);
				focusedIndex = index;
				drawButtonFocus(focusedIndex, false);
			}
			
			var child:Button = Button(getChildAt(index));
			simulatedClickTriggerEvent = trigger;
			child.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
			simulatedClickTriggerEvent = null;
		}
		
		//--------------------------------------------------------------------------
		//
		//  Overridden event handlers: UIComponent
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  @private
		 */
		override protected function keyDownHandler(event:KeyboardEvent):void
		{
			var targetIndex:int = -1;
			var updateFocusIndex:Boolean = true;
			var n:int = numChildren;
			
			switch (event.keyCode)
			{
				case Keyboard.PAGE_DOWN:
				{
					targetIndex = nextIndex(selectedIndex);
					break;
				}
					
				case Keyboard.PAGE_UP:
				{
					if (selectedIndex != -1)
						targetIndex = prevIndex(selectedIndex);
					else if (n > 0)
						targetIndex = 0;
					break;
				}
					
				case Keyboard.HOME:
				{
					if (n > 0)
						targetIndex = 0;
					break;
				}
					
				case Keyboard.END:
				{
					if (n > 0)
						targetIndex = n - 1;
					break;
				}
					
				case Keyboard.SPACE:
				case Keyboard.ENTER:
				{
					if (focusedIndex != -1)
					{
						targetIndex = focusedIndex;
						updateFocusIndex = false;
					}
					break;
				}
					
				default:
				{
					super.keyDownHandler(event);
				}
			}
			
			if (targetIndex != -1)
			{
				selectButton(targetIndex, updateFocusIndex, event);
			}
			
			event.stopPropagation();
		}
		
		/**
		 *  @private
		 */
		override protected function keyUpHandler(event:KeyboardEvent):void
		{
			// Override superclass's keyUpHandler() but do nothing.
		}
		
		//--------------------------------------------------------------------------
		//
		//  Overridden event handlers: NavBar
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  @private
		 */
		override protected function clickHandler(event:MouseEvent):void
		{
			var index:int = getChildIndex(Button(event.currentTarget));
			
			// 143958
			_selectedIndex = index;
			
			if (_toggleOnClick && index == selectedIndex)
			{
				selectedIndex = -1;
				hiliteSelectedNavItem(-1);
			}
			else
				hiliteSelectedNavItem(index);
			
			super.clickHandler(event);
		}
	}
}